package whf.framework.jdbc;

import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Map;

import javax.sql.DataSource;

import whf.framework.meta.Meta;
import whf.framework.security.UserContext;
import whf.framework.service.SpringService;
import whf.framework.util.StringUtils;
import whf.framework.util.ThreadContext;
import whf.framework.util.Utils;

/**
 * 可以根据上下文,动态分派数据库联接的数据源<br>
 * 搜索数据源的顺序:<br>
 * 1.线程当前数据源名称(手工输入的,优先级最高)
 * 2.从对象定义中获取;
 * 3.获取用户当前所在的数据源分支,从UserContext中获取;
 * 4.使用缺省
 * @author King
 *
 */
public class DispatchableDataSource extends SpringService implements DataSource {
	
	private Map<String, DataSource> registeredDataSources = Utils.newHashMap();
	
	private String defaultDataSourceName;
	
	public void setRegisteredDataSources(Map<String, DataSource> registeredDataSource) {
		this.registeredDataSources = registeredDataSource;
	}

	public void setDefaultDataSourceName(String defaultDataSourceName) {
		this.defaultDataSourceName = defaultDataSourceName;
	}

	private DataSource getCurrentDataSource() {
		String dsn = ThreadContext.getCurrentDataSourceName();
		Meta meta = ThreadContext.getCurrentMeta();
		if(meta != null && StringUtils.isEmpty(dsn)) {
			dsn = meta.getBranch();
		}
		if(StringUtils.isEmpty(dsn)) {
			UserContext uc = ThreadContext.getUserContext();
			if(uc != null) 
				dsn = uc.getBranch();
		}
		if(StringUtils.isEmpty(dsn))
			dsn = this.defaultDataSourceName;
		System.out.println("DataSourceName: "+dsn);
		return this.registeredDataSources.get(dsn);
	}

	@Override
	public int getLoginTimeout() throws SQLException {
		return this.getCurrentDataSource().getLoginTimeout();
	}

	@Override
	public PrintWriter getLogWriter() throws SQLException {
		return this.getCurrentDataSource().getLogWriter();
	}

	@Override
	public void setLoginTimeout(int seconds) throws SQLException {
		this.getCurrentDataSource().setLoginTimeout(seconds);
	}

	@Override
	public void setLogWriter(PrintWriter out) throws SQLException {
		this.getCurrentDataSource().setLogWriter(out);
	}

	@Override
	public Connection getConnection() throws SQLException {
		return this.getCurrentDataSource().getConnection();
	}

	@Override
	public Connection getConnection(String username, String password) throws SQLException {
		return this.getCurrentDataSource().getConnection(username, password);
	}

	@Override
	public boolean isWrapperFor(Class<?> iface) throws SQLException {
		return this.getCurrentDataSource().isWrapperFor(iface);
	}

	@Override
	public <T> T unwrap(Class<T> iface) throws SQLException {
		return this.getCurrentDataSource().unwrap(iface);
	}

	@Override
	public void afterPropertiesSet() throws Exception {
		if(StringUtils.isEmpty(this.defaultDataSourceName)) 
			throw new Exception("Default datasource name can not be empty!");
		if(this.registeredDataSources.get(this.defaultDataSourceName) == null) 
			throw new Exception("Can not found default datasource for default dataSourceName:" + this.defaultDataSourceName);
		super.afterPropertiesSet();
	}
	
}
